﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Kaesoft.Hospedaje.Entities;
using Kaesoft.Hospedaje.Common;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Kaesoft.Hospedaje.Proxy;
using System.Linq;
using Kaesoft.Hospedaje.Proxy.AdministracionReference;
using System.ComponentModel;

namespace Kaesoft.Hospedaje.Admin
{
    public class ArbolPerfilViewModel : ViewModelBase
    {
        private Arbol _nodoSeleccinando;
        private List<Arbol> _lstPerfil;
        public Perfil PerfilInsertado;
        private RelayCommand _eliminarCommand;
        private ArbolOpcionesPerfilViewModel _viewModelArbolOpciones;
        public event EventHandler<EventArgs<Arbol>> OnNodoSeleccionado;
        public event EventHandler<EventArgs<bool>> ItemCargado;
        public event EventHandler<EventArgs<bool>> OnCargando;
        public event EventHandler<EventArgs<bool>> AsignacionVerificada;
        private List<PerfilOpcionOperacion> _lstPerfilOpcionOperacionAdd;
        private List<PerfilOpcionOperacion> _lstPerfilOpcionOperacionDelete;
        public event EventHandler SetEdition;
        public event EventHandler SaveCompleted;
        private ArbolPerfilViewModel _viewModelArbolPerfil;
        public event EventHandler<EventArgs<bool>> EstadoProcesando;
        private bool _isEnabledControl;
        public event EventHandler EliminarCompleted;

        #region eventos

        public void OnEliminarCompleted()
        {
            if (EliminarCompleted != null)
                EliminarCompleted(this, new EventArgs());
        }


        public void OnEstadoProcesando(bool estado)
        {
            if (EstadoProcesando != null)
                EstadoProcesando(this, new EventArgs<bool>(estado));
        }


        public void OnSaveCompleted()
        {
            if (SaveCompleted != null)
                SaveCompleted(this, new EventArgs());
        }

        public void OnSetEdition()
        {
            if (SetEdition != null)
                SetEdition(this, new EventArgs());
        }



        #endregion



        public bool IsEnabledControl
        {
            get { return _isEnabledControl; }
            set
            {
                if (_isEnabledControl != value)
                {
                    _isEnabledControl = value;
                    OnPropertyChanged("IsEnabledControl");
                }
            }
        }
        public RelayCommand EliminarCommand { get { return _eliminarCommand ?? (_eliminarCommand = new RelayCommand(Eliminar)); } }

        public List<PerfilOpcionOperacion> LstPerfilOpcionoperacionEliminar
        {
            get { return _lstPerfilOpcionOperacionDelete; }
            set
            {
                if (_lstPerfilOpcionOperacionDelete != value)
                {
                    _lstPerfilOpcionOperacionDelete = value;
                    OnPropertyChanged("LstPerfilOpcionoperacionEliminar");
                }
            }
        }
        public List<PerfilOpcionOperacion> LstPerfilOpcionOperacionAgergar
        {
            get { return _lstPerfilOpcionOperacionAdd; }
            set
            {
                if (_lstPerfilOpcionOperacionAdd != value)
                {
                    _lstPerfilOpcionOperacionAdd = value;
                    OnPropertyChanged("LstPerfilOpcionOperacionAgergar");
                }
            }
        }

        public ArbolPerfilViewModel ViewModelArbolPerfil
        {
            get { return _viewModelArbolPerfil; }
            set
            {
                if (_viewModelArbolPerfil != value)
                {
                    _viewModelArbolPerfil = value;
                    OnPropertyChanged("ViewModelArbolPerfil");
                }
            }
        }



        public List<Arbol> LstPerfil
        {
            get { return _lstPerfil; }
            set
            {
                if (_lstPerfil != value)
                {
                    _lstPerfil = value;
                    OnPropertyChanged("LstPerfil");
                }
            }
        }
        public ArbolOpcionesPerfilViewModel ViewModelArbolOpciones
        {
            get { return _viewModelArbolOpciones; }
            set
            {
                if (_viewModelArbolOpciones != value)
                {
                    _viewModelArbolOpciones = value;
                    OnPropertyChanged("ViewModelArbolOpciones");
                }
            }
        }




        public Arbol NodoSeleccionado
        {
            get { return _nodoSeleccinando; }
            set
            {
                _nodoSeleccinando = value;
                OnPropertyChanged("NodoSeleccionado");
                SeleccionarNodo(value);
            }

        }
        /// <summary>
        /// Ejecutado cuando selecciona un nodo del árbol
        /// </summary>
        /// <param name="parameter">Parámetro</param>
        private void SeleccionarNodo(object parameter)
        {
            if (OnNodoSeleccionado != null && parameter != null)
                OnNodoSeleccionado(null, new EventArgs<Arbol>((Arbol)parameter));
        }

        private void CargarPerfiles(Arbol resultado)
        {
            #region Implementación
            //_seleccionado = resultado;
            ProxyAdministracion.ListarArbolPerfilesAsync(ev => obtenerDatosPerfiles(resultado, ev));
            #endregion
        }

        private void obtenerDatosPerfiles(object sender, ListarArbolPerfilesCompletedEventArgs e)
        {
            Arbol elementoTitulo = sender as Arbol;
            if (e.Error != null)
            {
                return;
            }
            if (e.Result.Count > 0)
            {
                elementoTitulo.ArbolHijo = new ObservableCollection<Arbol>();
                var nivelHijo = elementoTitulo.Nivel + 1;
                e.Result.ForEach(a =>
                {
                    a.Bandera = true;
                    if (PerfilInsertado != null)
                    {
                        if (a.idPerfil == PerfilInsertado.idPerfil)
                            a.Bandera = false;
                    }

                    elementoTitulo.ArbolHijo.Add(new Arbol()
                    {
                        Id = Guid.NewGuid(),
                        nombre = a.nombre,
                        Entidad = a,
                        Nivel = nivelHijo
                    });
                    ((INotifyPropertyChanged)a).PropertyChanged += new PropertyChangedEventHandler(ArbolPerfilViewModel_PropertyChanged);

                });
            }
            if (elementoTitulo.ArbolHijo.Count > 0)
            {
                elementoTitulo.ArbolHijo.ToList().ForEach(oc =>
                {
                    if (oc.Entidad is Perfil)
                    {
                        if (PerfilInsertado != null)
                        {
                            if (((Perfil)oc.Entidad).idPerfil == PerfilInsertado.idPerfil)
                                NodoSeleccionado = oc;
                        }
                    }
                });
            }

            if (NodoSeleccionado != null)
                ((Perfil)NodoSeleccionado.Entidad).Bandera = true;

            EstadoItemCargado(true);
            OnEstadoProcesando(false);
        }

        void ArbolPerfilViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            IsDirty = true;
            OnSetEdition();
        }
        /// <summary>
        /// Funcion que dispara un evento en el momento que los items estan cargados  
        /// </summary>
        /// <param name="param"></param>
        private void EstadoItemCargado(bool param)
        {
            if (ItemCargado != null)
                ItemCargado(this, new EventArgs<bool>(param));
        }

        #region Constructor
        public ArbolPerfilViewModel()
        {
            MessageBoxWindow = new MessageWindowView();
            if (!Design.IsInDesignModeStatic)
            {
                InicializaArbolPerfiles();
            }
        }
        public void InicializaArbolPerfiles()
        {
            LstPerfil = new List<Arbol>();
            var perfilTmp = new Perfil() { idPerfil = Guid.Empty, nombre = "Perfiles", Bandera = true };
            List<Perfil> perfilEntidad = new List<Perfil>() { perfilTmp };
            perfilEntidad.ForEach(a => LstPerfil.Add(new Arbol() { Id = Guid.NewGuid(), nombre = a.nombre, Entidad = a, Nivel = 0 }));

            CargarPerfiles(LstPerfil.First());


        }
        #endregion


        private void ActualizaPerfilFCompleted(object sender, ActualizaPerfilFCompletedEventArgs e)
        {
            IsDirty = false;
            OnSaveCompleted();
            if (e.Error != null)
                return;
            if (NodoSeleccionado.Entidad is Perfil)
            {
                PerfilInsertado = null;
                InicializaArbolPerfiles();
            }
        }

        /// <summary>
        /// Funcion completed del metodo asincrono ActualizaPerfil
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ActualizaPerfilCompleted(object sender, ActualizaPerfilCompletedEventArgs e)
        {
            if (e.Error != null)
                return;
            else
            {
                if (e.Result)
                {
                    var listaACargarOpcionOperacion = ViewModelArbolOpciones.ListaPerfilOpcionOperacionActual;
                    var listaACArgarOpcion = ViewModelArbolOpciones.ListaPerfilOpcionActual;
                    ViewModelArbolOpciones.ListaPerfilOpcionOperacionActual = listaACargarOpcionOperacion;

                    ViewModelArbolOpciones.LstPerfilOpcionOperacionAgergar.ForEach(a =>
                    {
                        ViewModelArbolOpciones.ListaPerfilOpcionOperacionActual.Add(a);
                    });

                    ViewModelArbolOpciones.LstPerfilOpcionoperacionEliminar.ForEach(a =>
                    {
                        var existe = ViewModelArbolOpciones.ListaPerfilOpcionOperacionActual.Where(l => l.idPerfil == a.idPerfil && l.idOperacion == a.idOperacion && l.idOpcion == a.idOpcion).FirstOrDefault();
                        if (existe != null)
                            ViewModelArbolOpciones.ListaPerfilOpcionOperacionActual.Remove(ViewModelArbolOpciones.ListaPerfilOpcionOperacionActual.Where(l => l.idPerfil == a.idPerfil && l.idOperacion == a.idOperacion && l.idOpcion == a.idOpcion).First());
                    });

                    ViewModelArbolOpciones.ListaPerfilOpcionAgregar.ForEach(a =>
                    {
                        ViewModelArbolOpciones.ListaPerfilOpcionActual.Add(a);
                    });

                    ViewModelArbolOpciones.ListaPerfilOpcionEliminar.ForEach(a =>
                    {
                        var existe = ViewModelArbolOpciones.ListaPerfilOpcionActual.Where(l => l.idPerfil == a.idPerfil && l.idOpcion == a.idOpcion).FirstOrDefault();
                        if (existe != null)
                            ViewModelArbolOpciones.ListaPerfilOpcionActual.Remove(ViewModelArbolOpciones.ListaPerfilOpcionActual.Where(l => l.idPerfil == a.idPerfil && l.idOpcion == a.idOpcion).First());
                    });

                    ((Perfil)NodoSeleccionado.Entidad).Bandera = true;

                    ViewModelArbolOpciones.LstPerfilOpcionOperacionAgergar = new List<PerfilOpcionOperacion>();
                    ViewModelArbolOpciones.LstPerfilOpcionoperacionEliminar = new List<PerfilOpcionOperacion>();



                }
            }
            EstadoCargandoCambiado(false);
        }

        /// Funcion que dispara un evento para cambiar el estado del bussy indicator
        /// </summary>
        /// <param name="param"></param>
        private void EstadoCargandoCambiado(bool param)
        {
            if (OnCargando != null)
                OnCargando(null, new EventArgs<bool>(param));
        }

        /// <summary>
        /// Funcion que permite guardar el perfil actual
        /// </summary>
        /// <param name="elementoPerfil"></param>
        public void GuardaPerfilActual(Perfil elementoPerfil)
        {
            //EstadoCargandoCambiado(true);
            MessageWindowViewModel msgWindowViewModel = new MessageWindowViewModel("Ya existe un perfil con ese nombre", MessageBoxButtons.Ok, MessageBoxIcon.Error);
            MessageBoxWindow.DataContext = msgWindowViewModel;
            msgWindowViewModel.Closing += (msgsender, ev) =>
            {
                MessageBoxWindow.Close();
                //  EstadoCargandoCambiado(false);
                if (ev.Data != MessageBoxResult.OK) return;
            };
            ProxyAdministracion.ObtenerPerfilPorNombreAsync(elementoPerfil.nombre, (evn) =>
            {
                if (evn.Error != null)
                    return;
                if (evn.Result != null)
                    MessageBoxWindow.Show();
                else
                    ProxyAdministracion.InsertarNuevoPerfilAsync(elementoPerfil, ev => InsertarNuevoPerfilCompleted(null, ev));
            });

        }

        /// <summary>
        /// Funcion completed del metodo asincrono InsertaNuevoPerfil
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void InsertarNuevoPerfilCompleted(object sender, InsertarNuevoPerfilCompletedEventArgs e)
        {
            if (e.Error != null)
                return;

            if (e.Result != null)
            {
                //if (NodoSeleccionado.Entidad is Perfil)
                //{
                //    if (((Perfil)NodoSeleccionado.Entidad).idPerfil == Guid.Empty)
                //    {
                PerfilInsertado = e.Result;
                InicializaArbolPerfiles();
                //    }
                //}


            }
            //EstadoCargandoCambiado(false);

        }

        /// <summary>
        /// Funcion que permite modificar el perfil actual
        /// </summary>
        /// <param name="perfilNombre"></param>
        /// <param name="perfilId"></param>
        /// <param name="poEliminar"></param>
        /// <param name="poAgregar"></param>
        /// <param name="pooEliminar"></param>
        /// <param name="pooAgregar"></param>
        public void ActualizarPerfilActual(string perfilNombre, Guid perfilId, List<PerfilOpcion> poEliminar, List<PerfilOpcion> poAgregar, List<PerfilOpcionOperacion> pooEliminar, List<PerfilOpcionOperacion> pooAgregar)
        {
            EstadoCargandoCambiado(true);
            ProxyAdministracion.ActualizaPerfilAsync(perfilNombre, perfilId, poEliminar, poAgregar, pooEliminar, pooAgregar, ev => ActualizaPerfilCompleted(null, ev));
        }


        public void ActualizarPerfilM(string perfilNombre, Guid perfilId)
        {
            EstadoCargandoCambiado(true);
            ProxyAdministracion.ActualizaPerfilFAsync(perfilNombre, perfilId, ev => ActualizaPerfilFCompleted(null, ev));

        }

        /// <summary>
        /// Funcion origen para la eliminacion de un perfil completo
        /// </summary>
        /// <param name="parameter"></param>
        private void Eliminar(object parameter)
        {
            MessageWindowViewModel msgWindowViewModel = new MessageWindowViewModel("Está seguro de borrar los elementos seleccionados? Perderá también los cambios en los elementos no guardados.",
                                                                                   MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            MessageBoxWindow.DataContext = msgWindowViewModel;
            msgWindowViewModel.Closing += (msgsender, ev) =>
            {
                MessageBoxWindow.Close();
                if (ev.Data != MessageBoxResult.Yes) return;

                Procesando = true;

                var lista = (from p in LstPerfil.First().ArbolHijo where p.Seleccionado && ((Perfil)p.Entidad).idPerfil != Guid.Empty select p).ToList();
                List<Perfil> listaPerfiles = new List<Perfil>();
                lista.ForEach(a => listaPerfiles.Add((Perfil)a.Entidad));
                VerificaAsignacion(listaPerfiles);
                OnEliminarCompleted();
            };
            MessageBoxWindow.ShowDialog();
        }

        /// <summary>
        /// funcion que verifica si el perfil se encuentra asignado
        /// </summary>
        /// <param name="perfiles"></param>
        private void VerificaAsignacion(List<Perfil> perfiles)
        {
            bool confirmarExistencia = false;
            int contador = 0;
            var tontojil = perfiles;

            var errorText = "No se puede eliminar un perfil que ya está asignado a uno o mas usuarios";
            MessageWindowViewModel msgWindowViewModel = new MessageWindowViewModel(errorText, MessageBoxButtons.Ok, MessageBoxIcon.Question);
            MessageBoxWindow.DataContext = msgWindowViewModel;
            msgWindowViewModel.Closing += (msgsender, ev) =>
            {
                MessageBoxWindow.Close();
                Procesando = false;
                if (ev.Data != MessageBoxResult.OK) return;
            };


            MessageBoxWindow.Close();

            perfiles.ForEach(a => ProxyAdministracion.ObtenerPerfilPorIdAsync(a.idPerfil, ev =>
            {
                contador++;
                if (ev.Error != null)
                    return;
                if (((Perfil)ev.Result).Asignado)
                    confirmarExistencia = true;
                if (contador == perfiles.Count)
                {
                    AsignacionVerificada += (sender, eve) =>
                    {
                        var sendergf = sender;
                        if (!confirmarExistencia)
                            ProxyAdministracion.EliminaPerfilesAsync((List<Perfil>)sender, (evn) =>
                            {
                                if (evn.Error != null)
                                    return;
                                if (evn.Result)
                                    InicializaArbolPerfiles();
                            });
                        else
                        {
                            MessageBoxWindow.Show();
                            confirmarExistencia = false;
                        }
                    };

                    if (AsignacionVerificada != null)
                        AsignacionVerificada(perfiles, new EventArgs<bool>(true));
                }
            }));
        }

        public void guardar(Perfil perfilActual)
        {
            ActualizarPerfilM(perfilActual.nombre, perfilActual.idPerfil);
        }

        public void ModoEdicion(bool editable)
        {
            IsEnabledControl = editable;
        }
    }
}
